package ${tempValues.package_this_file};

import org.apache.dubbo.common.status.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;


@Controller
public class HealthController {
    private Logger logger = LoggerFactory.getLogger(HealthController.class);

    @Resource
    private DubboStatusChecker dubboStatusChecker;

    private static final String OK = "ok";
    private static final String NOT_OK = "not_ok";

    private static final String HEARTBEAT = "heartbeat";
    private static final String OFFLINE = "offline";
    private static final String ONLINE = "online";
    private static final String HEALTH_CHECK = "healthCheck";

    private static String flag = NOT_OK;

    List<String> localHostIpList = new ArrayList<String>() {{
        add("127.0.0.1");
        add("localhost");
        add("0:0:0:0:0:0:0:1");
    }};

    @RequestMapping("/hc.do")
    @ResponseBody
    public String doHealthCheck(@RequestParam String a, HttpServletRequest request, HttpServletResponse response) {
        String ip = request.getRemoteAddr();
        String result = NOT_OK;
        switch (a) {
            case HEARTBEAT:
                result = flag;
                break;
            case OFFLINE:
                // 注意要限制本地ip访问
                if (localHostIpList.contains(ip)) {
                    flag = NOT_OK;
                    // 如果dubbo的，要从注册中心下线自己节点。kafka也类似，没有使用kafka或者dubbo的可以不需要。
                    // KafkaLifeCycleController.stopConsumer();
                    DubboShutdowner.stopDubbo();
                    result = OK;
                    break;
                }
            case ONLINE:
                // 注意要限制本地ip访问
                if (localHostIpList.contains(ip)) {
                    flag = OK;
                    result = OK;
                    break;
                }
            case HEALTH_CHECK:
                result = OK;
//                Status status = allCheck();
//                result = status == null ? OK : NOT_OK;
                break;
        }
        // 如果返回不是ok，返回状态码也要返回4xx 或者 5xx
        if (NOT_OK.equals(result)) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
        return result;
    }


    /****************************************************************************************/
    /***************************************private******************************************/
    /****************************************************************************************/

    private Status allCheck() {
        Status status = dubboStatusChecker.checkMemory();
        if (!isOk(status)) {
            logger.error("Dubbo内存检查失败，请确保可用内存大小大于2M");
            return status;
        }
        status = dubboStatusChecker.checkServer();
        if (!isOk(status)) {
            logger.error("Dubbo服务端检查失败，请确保Server端启动成功");
            return status;
        }
//        status = dubboStatusChecker.checkThreadPool();
//        if (!isOk(status)) {
//            logger.error("Dubbo线程池检查失败，如果Dubbo版本>=2.7.8， 请确保baisc-dubbo-ext插件版本>=3.1.5");
//            return status;
//        }
        status = dubboStatusChecker.checkRegistry();
        if (!isOk(status)) {
            logger.error("Dubbo注册中心检查失败，请确保至少有一个注册中心启动成功");
            return status;
        }
//        status = dubboStatusChecker.checkDataSource();
//        if (!isOk(status)) {
//            logger.error("Dubbo数据源检查失败，如果项目中没有用到Datasource数据源，可以把该检查项移除");
//            return status;
//        }
        return null;
    }

    private boolean isOk(Status status) {
        if (!status.getLevel().name().equals("OK")) {
            return false;
        }
        return true;
    }

}
